home *** CD-ROM | disk | FTP | other *** search
- // Provides low-level screen support through the TxBuff object
- #include <dos.h>
- #include "txunit.h"
-
- #define True 1
- #define False 0
-
- TxBuff::TxBuff(TexelPtr T)
- // Initializes a TxBuff object. T is a pointer to the texel buffer
- // to use or 0 if TxBuff is supposed to allocate its own texel
- // buffer.
- {
- Wd = 0; Ht = 0;
- SetRamPtr(T);
- }
-
- TxBuff::TxBuff(int W, int H, TexelPtr T)
- // Initializes a TxBuff object. T is a pointer to the texel buffer
- // to use or 0 if TxBuff is supposed to allocate its own texel
- // buffer. Then, the width and height are set.
- {
- SetRamPtr(T);
- SetSize(W, H);
- }
-
- void TxBuff::SetRamPtr(TexelPtr T)
- // Initializes a TxBuff object. T is a pointer to the texel buffer
- // to use or 0 if TxBuff is supposed to allocate its own texel
- // buffer.
- {
- if (T) {
- Aliased = True;
- Txram = T;
- }
- else {
- Aliased = False;
- Txram = 0;
- }
- OrgPtr = Txram;
- }
-
- TxBuff::~TxBuff(void)
- // Free texel buffer in TxBuff if object was not aliased
- {
- if (!Aliased) delete[Wd*Ht] Txram;
- }
-
- TexelPtr TxBuff::TxramAddr(int X, int Y)
- // Computes pointer for (X,Y) location relative to Txram
- {
- return Txram + Y*Wd + X;
- }
-
- TexelPtr TxBuff::RelAddr(int X, int Y)
- // Computes pointer for (X,Y) location relative to OrgPtr
- {
- return OrgPtr + Y*Wd + X;
- }
-
- void TxBuff::SetSize(int W, int H)
- // Set size of texel buffer. If not aliased, and the size
- // has been set before, don't reallocate memory unless the
- // new size is bigger.
- {
- if (!Aliased) { // Want buffer on heap
- if (!Txram) { // Allocate for first time
- Txram = new Texel[W*H];
- }
- else if (W*H > Wd*Ht) { // Reallocate?
- delete [Wd*Ht] Txram;
- Txram = new Texel[W*H];
- }
- OrgPtr = Txram;
- }
- Wd = W; Ht = H;
- }
-
- void TxBuff::SetLocn(int X, int Y)
- // Set location of OrgPtr--which is the pointer into TxBuff which
- // operations such as Fill, FillB, HzWrt and so on, are with
- // respect to
- {
- OrgPtr = TxramAddr(X, Y);
- }
-
- void TxBuff::Swap(int X, int Y, int W, int H, TxBuff *Other, int Xs, int Ys)
- // Swaps data between the Other Txbuff, starting as (Xs, Ys)
- // and this object's OrgPtr, starting at X,Y, and swapping a region
- // of width W, height H. The swap takes place row by row.
- // We handle possible memory overlap by reversing the directions
- // of the swap, assuming that the only way overlap can occur
- // is when we're swapping memory within ourselves.
- {
- int I, J;
- Texel T;
- TexelPtr Dp, Sp;
- Dp = RelAddr(X, Y);
- Sp = Other->RelAddr(Xs, Ys);
- if (FP_OFF(Sp) < FP_OFF(Dp)) { // Might need to switch directions
- for (I=0; I<H; I++) {
- Dp = RelAddr(X, Y+I);
- Sp = Other->RelAddr(Xs, Ys+I);
- for (J=0; J<W; J++) {
- T = *Dp;
- *Dp++ = *Sp;
- *Sp++ = T;
- }
- }
- }
- else {
- for (I=H-1; I>=0; I--) {
- Dp = RelAddr(X, Y+I) + W;
- Sp = Other->RelAddr(Xs, Ys+I) + W;
- for (J=0; J<W; J++) {
- T = *(--Dp);
- *Dp = *(--Sp);
- *Sp = T;
- }
- }
- }
- }
-
- void TxBuff::Xfr(int X, int Y, int W, int H, TxBuff *Other, int Xs, int Ys)
- // Transfers data from the Other Txbuff, starting as (Xs, Ys) into
- // this object's OrgPtr, starting at X,Y, and transferring a region
- // of width W, height H. The transfer takes place row by row.
- // We handle possible memory overlap by reversing the directions
- // of the transfer, assuming that the only way overlap can occur
- // is when we're transferring memory within ourselves.
- {
- int I, J;
- TexelPtr Dp, Sp;
- Dp = RelAddr(X, Y);
- Sp = Other->RelAddr(Xs, Ys);
- if (FP_OFF(Dp) < FP_OFF(Sp)) { // Might need to switch directions
- for (I=0; I<H; I++) {
- Dp = RelAddr(X, Y+I);
- Sp = Other->RelAddr(Xs, Ys+I);
- for (J=0; J<W; J++) *Dp++ = *Sp++;
- }
- }
- else {
- for (I=H-1; I>=0; I--) {
- Dp = RelAddr(X, Y+I) + W;
- Sp = Other->RelAddr(Xs, Ys+I) + W;
- for (J=0; J<W; J++) *(--Dp) = *(--Sp);
- }
- }
- }
-
- void TxBuff::Scroll(int X, int Y, int W, int H, ScrollDir Sd, int Amt)
- // Scroll the text in a specified direction by doing
- // overlapping transfers with Self
- {
- switch(Sd) {
- case UpScroll: Xfr(X, Y, W, H, this, X, Y+Amt); break;
- case DnScroll: Xfr(X, Y+Amt, W, H, this, X, Y); break;
- case LeftScroll: Xfr(X, Y, W, H, this, X+Amt, Y); break;
- case RightScroll: Xfr(X+Amt, Y, W, H, this, X, Y); break;
- default: ;
- }
- }
-
- void TxBuff::Fill(int X, int Y, int W, int H, char Ch, char Attr)
- // Fill a rectangular region with a particular character and
- // attribute. The coordinates are relative to this canvas.
- {
- for (int I=0; I<H; I++) {
- TexelPtr Tp = RelAddr(X, Y+I);
- for (int J=0; J<W; J++) {
- Tp->Ch = Ch;
- Tp->Attr = Attr;
- Tp++;
- }
- }
- }
-
- void TxBuff::FillB(int X, int Y, int W, int H, char Ch, char Opt)
- // Fill either the character or the attribute fields in a
- // rectangular region. The coordinates are relative to this canvas
- {
- for (int I=0; I<H; I++) {
- char far *P = (char far *)RelAddr(X,Y+I);
- if (Opt) P++; // Skip over char byte
- for (int J=0; J<W; J++) {
- *P = Ch;
- P += 2;
- }
- }
- }
-
-
- void TxBuff::HzWrt(int X, int Y, char *Str, char Attr, unsigned Cnt)
- // Writes to (X,Y) locn (relative to OrgPtr)
- {
- TexelPtr Tp = RelAddr(X, Y);
- for (int I=0; I<Cnt; I++, Tp++) {
- Tp->Ch = *Str++;
- Tp->Attr = Attr;
- }
- }
-
- void TxBuff::HzWrtB(int X, int Y, char *Str, unsigned Cnt)
- // Writes to (X,Y) locn (relative to OrgPtr)
- {
- char far *P = (char far *)RelAddr(X, Y);
- for (int J=0; J<Cnt; J++) {
- *P = *Str++;
- P += 2; // Skip over attribute
- }
- }
-
- TexelPtr VideoPtr(unsigned &Vmode, unsigned &Vpage)
- // Discover what text mode we're in, and return video addr
- {
- union REGS Regs;
- unsigned Segment, Offset;
- Regs.h.ah = 15;
- int86(0x10, &Regs, &Regs);
- Vmode = Regs.h.al; Vpage = Regs.h.bh;
- if (Vmode == 7) Segment = 0xb000; else Segment = 0xb800;
- Offset = Vpage * (unsigned)0x1000;
- return TexelPtr((long(Segment) << 16) | long(Offset));
- }
-
- TexelPtr VideoPtr(void)
- {
- unsigned Vm, Vp;
- return VideoPtr(Vm, Vp);
- }
-